<?php
if ( ! defined( 'ABSPATH' ) ) {
	exit;
}

/**
 * Tour Query
 *
 * @author  physcode
 * @version 1.2.7
 */
class TravelPhysQuery {
	public function __construct() {
		if ( ! is_admin() ) {
			add_action( 'pre_get_posts', array( $this, 'filter_pre_get_posts' ), 15 );
			add_filter( 'query_vars', array( $this, 'filter_query_vars' ) );
			add_action( 'wp', array( $this, 'remove_tour_query' ) );
		} else {
			if ( ! wp_doing_ajax() ) {
				add_action( 'pre_get_posts', array( $this, 'query_get_posts_product_admin' ), 16, 1 );
			}
		}
	}

	public function filter_pre_get_posts( $q ) {
		if ( ! $q->is_main_query() ) {
			return;
		}

		$tax_product = 'product';
		$tax_tour    = 'tour_phys';
		global $wp;
		$current_url          = home_url( add_query_arg( array(), $wp->request ) ) . '/';
		$_tours_show_page_id  = Tour_Settings_Tab_Phys::$_tours_show_page_id;
		$link_page_show_tours = get_page_link( (int) get_option( $_tours_show_page_id ) );

		if ( $GLOBALS['wp_rewrite']->use_verbose_page_rules && $current_url == $link_page_show_tours ) {
			$this->query_for_tour( $q );

			return;
		}

		if ( $q->get( 'is_hotel' ) ) {
			return;
		}

		if ( $q->get( 'is_tour' ) ) {
			$this->query_for_tour( $q );
		} elseif ( $q->get( 'tour_search' ) ) {
			$q = $this->query_for_tour( $q );

			if ( $q->get( 'name_tour' ) ) {
				$q->set( 's', $q->get( 'name_tour' ) );
			}

			$tax_query_attribute = array(
				array(
					'taxonomy' => 'product_type',
					'field'    => 'slug',
					'terms'    => array( 'tour_phys' ),
					'operator' => 'IN',
				)
			);

			if ( $q->get( 'tourtax' ) ) {
				foreach ( $q->get( 'tourtax' ) as $key => $tax_attribute ) {
					if ( $tax_attribute != '0' ) {
						$q_term                = array(
							'taxonomy' => $key,
							'field'    => 'slug',
							'terms'    => array( $tax_attribute ),
							'operator' => 'IN',
						);
						$tax_query_attribute[] = $q_term;
					}
				}

				$q->set( 'tax_query', $tax_query_attribute );
			}

			//			$args['meta_query'] = $q->get( 'meta_query' );
			$args                           = array();
			$args['meta_query']['relation'] = 'AND';

			if ( $q->get( 'tour_min_price' ) && $q->get( 'tour_max_price' ) ) {
				$tour_price_min = $q->get( 'tour_min_price' );
				$tour_price_max = $q->get( 'tour_max_price' );

				$args['meta_query'][] = array(
					'key'     => '_price',
					'value'   => array( $tour_price_min, $tour_price_max ),
					'compare' => 'BETWEEN',
					'type'    => 'DECIMAL(10,' . wc_get_price_decimals() . ')',
				);
			}

			if ( $q->get( 'tour_code' ) ) {
				$args['meta_query'][] = array(
					'key'     => '_tour_code',
					'value'   => $q->get( 'tour_code' ),
					'compare' => '='
				);
			}

			if ( $q->get( 'tour_rating' ) ) {
				$args['meta_query'][] = array(
					'key'     => '_wc_average_rating',
					'value'   => $q->get( 'tour_rating' ),
					'compare' => '>=',
					'type'    => 'DECIMAL'
				);
			}

			// Catalog visibility
			$args['meta_query'][] = array(
				'relation' => 'OR',
				array(
					'key'     => '_visibility',
					'value'   => 'visible',
					'compare' => '=',
				),
				array(
					'key'     => '_visibility',
					'value'   => 'search',
					'compare' => '=',
				),
				array(
					'key'     => '_visibility',
					'compare' => 'NOT EXISTS',
					'value'   => '',
				)
			);

			//var_dump($args['meta_query']);

			$q->set( 'meta_query', $args['meta_query'] );

		} elseif ( $q->get( 'is_single_tour' ) == 1 ) {
			$this->query_for_single_tour( $q );
		} elseif ( 'product' == $q->get( 'post_type' ) ) {
			$q->set(
				'tax_query', array(
					array(
						'taxonomy' => 'product_type',
						'field'    => 'slug',
						'terms'    => array( 'simple', 'grouped', 'variable', 'external' ),
						'operator' => 'IN',
					)
				)
			);
		}

		$this->remove_tour_query();
	}

	public function query_get_posts_product_admin( $query ) {
		if ( $query->get( 'post_type' ) == 'product' ) {
			if ( $query->get( 'product_type' ) != 'tour_phys' ) {
				$query->set(
					'tax_query', array(
						array(
							'taxonomy' => 'product_type',
							'field'    => 'slug',
							'terms'    => array( 'tour_phys' ),
							'operator' => 'NOT IN',
						)
					)
				);
			}
		}
	}

	private function query_for_tour( $q ) {
		$q->set( 'is_tour', 1 );
		$q->set( 'wc_query', 'tours' );
		$q->set( 'post_type', 'product' );
		$q->set( 'page', '' );
		$q->set( 'pagename', '' );
		//		$q->set( 'orderby', 'rand' );
		//		$q->set( 'order', 'DESC' );

		$q->set(
			'tax_query', array(
				array(
					'taxonomy' => 'product_type',
					'field'    => 'slug',
					'terms'    => array( 'tour_phys' ),
					'operator' => 'IN',
				)
			)
		);

		$args               = array();
		$args['meta_query'] = $q->get( 'meta_query' );

		if ( ! is_array( $args['meta_query'] ) ) {
			$args['meta_query'] = array(
				'relation' => 'OR',
				array(
					'key'     => '_visibility',
					'value'   => 'visible',
					'compare' => '=',
				),
				array(
					'key'     => '_visibility',
					'value'   => 'catalog',
					'compare' => '=',
				),
				array(
					'key'     => '_visibility',
					'compare' => 'NOT EXISTS',
					'value'   => '',
				)
			);
		} else {
			$args['meta_query'][] = array(
				'relation' => 'OR',
				array(
					'key'     => '_visibility',
					'value'   => 'visible',
					'compare' => '=',
				),
				array(
					'key'     => '_visibility',
					'value'   => 'catalog',
					'compare' => '=',
				),
				array(
					'key'     => '_visibility',
					'compare' => 'NOT EXISTS',
					'value'   => '',
				)
			);
		}
		$q->set( 'posts_per_page', $q->get( 'posts_per_page' ) ? $q->get( 'posts_per_page' ) : apply_filters( 'loop_shop_per_page', get_option( 'posts_per_page' ) ) );

		$q->set( 'meta_query', $args['meta_query'] );

		// Fix conditional Functions
		$q->is_archive           = true;
		$q->is_post_type_archive = true;
		$q->is_singular          = false;
		$q->is_page              = false;

		$this->tour_query_order( $q );

		return $q;
	}

	private function query_for_single_tour( $q ) {
		if ( isset( $_GET['tours'] ) ) {
			$slug_tour = $_GET['tours'];

			$q->set( 'name', $slug_tour );

			$q->set( 'post_type', 'product' );

			$q->set(
				'tax_query', array(
					array(
						'taxonomy' => 'product_type',
						'field'    => 'slug',
						'terms'    => array( 'tour_phys' ),
						'operator' => 'IN',
					)
				)
			);

			return $q;
		}
	}

	public function filter_query_vars( $vars ) {
		$vars[] = 'is_tour';
		$vars[] = 'is_single_tour';
		$vars[] = 'tour_search';
		$vars[] = 'tourtax';
		$vars[] = 'name_tour';
		$vars[] = 'tour_code';
		$vars[] = 'tour_rating';
		$vars[] = 'tour_min_price';
		$vars[] = 'tour_max_price';

		return $vars;
	}

	public function tour_query_order( $q ) {
		// Ordering query vars
		$ordering = $this->get_catalog_ordering_args();
		$q->set( 'orderby', $ordering['orderby'] );
		$q->set( 'order', $ordering['order'] );
		if ( isset( $ordering['meta_key'] ) ) {
			$q->set( 'meta_key', $ordering['meta_key'] );
		}
	}

	public function get_catalog_ordering_args( $orderby = '', $order = '' ) {
		// Get ordering from query string unless defined
		if ( ! $orderby ) {
			$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );

			// Get order + orderby args from string
			$orderby_value = explode( '-', $orderby_value );
			$orderby       = esc_attr( $orderby_value[0] );
			$order         = ! empty( $orderby_value[1] ) ? $orderby_value[1] : $order;
		}
		//$orderby = 'price';
		$orderby = strtolower( $orderby );
		$order   = strtoupper( $order );
		$args    = array();

		// default - menu_order
		$args['orderby']  = 'menu_order title';
		$args['order']    = ( 'DESC' === $order ) ? 'DESC' : 'ASC';
		$args['meta_key'] = '';

		switch ( $orderby ) {
			case 'rand' :
				$args['orderby'] = 'rand';
				break;
			case 'date' :
				$args['orderby'] = 'date ID';
				$args['order']   = ( 'ASC' === $order ) ? 'ASC' : 'DESC';
				break;
			case 'price' :
				$args['orderby']  = "meta_value_num ID";
				$args['order']    = ( 'DESC' === $order ) ? 'DESC' : 'ASC';
				$args['meta_key'] = '_price';
				break;
			case 'popularity' :
				$args['meta_key'] = 'total_sales';

				// Sorting handled later though a hook
				add_filter( 'posts_clauses', array( $this, 'order_by_popularity_post_clauses' ) );
				break;
			case 'rating' :
				$args['meta_key'] = '_wc_average_rating';
				$args['orderby']  = array(
					'meta_value_num' => 'DESC',
					'ID'             => 'ASC',
				);
				break;
			case 'title' :
				$args['orderby'] = 'title';
				$args['order']   = ( 'DESC' === $order ) ? 'DESC' : 'ASC';
				break;
		}

		return apply_filters( 'hotel_get_catalog_ordering_args', $args );
	}

	public function order_by_popularity_post_clauses( $args ) {
		global $wpdb;
		$args['orderby'] = "$wpdb->postmeta.meta_value+0 DESC, $wpdb->posts.post_date DESC";

		return $args;
	}

	public function remove_tour_query() {
		remove_action( 'pre_get_posts', array( $this, 'filter_query_vars' ) );
	}
}

new TravelPhysQuery();